// 导入lodash-es库中的函数，用于深拷贝、对象键值对转换、自定义合并对象和数组去重
import { cloneDeep, keyBy, mergeWith, uniq } from 'lodash-es'
// 导入模型数据，作为默认参数用于以下函数
import model from '../model/index.js'

/**
 * 获取顶层字段数组
 * @param {Object} data - 模型数据，默认为整个模型
 * @returns {Array} - 顶层字段数组
 */
export function getTopFields(data = model) {
  return uniq(Object.values(data).map(item => item.field))
}

// 调用getTopFields函数，获取顶层字段数组
const topFields = getTopFields()

/**
 * 获取模型映射对象，将模型数据转换为便于操作的格式
 * @param {Object} data - 模型数据，默认为整个模型
 * @returns {Object} - 模型映射对象
 */
export function getModelMap(data = model) {
  const value = Object.entries(data).reduce((obj, [parentId, parentItem]) => {
    const children
      = Object.entries(parentItem?.children || {})?.map(([id, item]) => ({
        ...item,
        parentField: parentItem.field,
        parentId,
        id,
      })) || []

    const subData = keyBy(children, 'field')

    obj = {
      ...obj,
      ...subData,
    }

    return obj
  }, {})

  return value
}

/**
 * 获取默认数据，根据父ID和迭代函数来筛选和处理模型数据
 * @param {String} parentId - 父ID，用于筛选数据
 * @param {Function} iteratee - 迭代函数，用于处理每个数据项，默认为返回原值
 * @returns {Object} - 处理后的默认数据对象
 */
export function getDefaultData(parentId, iteratee) {
  const modelMap = getModelMap()

  iteratee = iteratee ?? (value => value)

  const value = Object.entries(modelMap).reduce((obj, [key, data]) => {
    if (!parentId || data.parentId === parentId) {
      obj[key] = iteratee(data.value)
    }
    return obj
  }, {})

  return value
}

/**
 * 获取存储数据，从全局存储中提取与顶层字段相关的数据
 * @param {String} scope - 作用域，用于获取特定范围的数据
 * @returns {Object} - 提取后的存储数据对象
 */
export const getStoreData = (scope) => {
  const value = {}

  topFields.forEach((key) => {
    const storeValue = window.appStore.get(key) || {}
    if (key === 'scrcpy') {
      Object.assign(value, storeValue[scope || 'global'])
      return
    }

    Object.assign(value, storeValue)
  })

  return value
}

/**
 * 设置存储数据，将数据根据模型映射更新到全局存储中
 * @param {Object} data - 要设置的数据对象
 * @param {String} scope - 作用域，用于设置特定范围的数据
 */
export function setStoreData(data, scope) {
  const modelMap = getModelMap()

  const storeModel = topFields.reduce((obj, key) => {
    obj[key] = {}
    return obj
  }, {})

  Object.entries(data).forEach(([key, value]) => {
    const { parentField } = modelMap?.[key] || {}

    if (!parentField) {
      return
    }

    storeModel[parentField][key] = value
  })

  const storeList = Object.entries(storeModel).reduce((arr, [field, value]) => {
    arr.push({
      field: field === 'scrcpy' ? `scrcpy.${scope}` : field,
      value,
    })
    return arr
  }, [])

  storeList.forEach((item) => {
    window.appStore.set(item.field, item.value)
  })
}

/**
 * 合并配置对象，自定义合并源对象到目标对象
 * @param {Object} object - 目标对象
 * @param {Object} sources - 源对象
 * @returns {Object} - 合并后的对象
 */
export function mergeConfig(object, sources) {
  const cloneObject = cloneDeep(object)
  const cloneSources = cloneDeep(sources)

  const customizer = (objValue, srcValue, key) => {
    let value

    if (srcValue) {
      value = srcValue
    }
    else if (objValue) {
      value = objValue
    }

    return value
  }

  const value = mergeWith(cloneObject, cloneSources, customizer)

  return value
}

/**
 * 获取其他字段数组，排除指定父字段的数据项
 * @param {String} excludeKey - 排除的父字段，默认为空
 * @returns {Array} - 其他字段数组
 */
export const getOtherFields = (excludeKey = '') => {
  const modelMap = getModelMap()
  const value = Object.values(modelMap).reduce((arr, item) => {
    if (item.parentField !== excludeKey) {
      arr.push(item.field)
    }
    return arr
  }, [])

  return value
}
